package bby.app.fettool;

import bby.app.keytools.AES;
import bby.app.keytools.MD5;
import bby.app.keytools.RSA;
import bby.tools.BBYFileTool;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.nio.ByteBuffer;

public class SenderPage extends JPanel implements ActionListener {
    JTextField portInput,hostInput,keyInput,pubKeyView,textMsg;
    JTextArea outMsg;
    JPanel title,msgBody,pubKeyBody,fileBody,fileBtBody;
    JButton connectBt,selFileBt,sendBt,enFileBt,deFileBt,openFileBt;
    JProgressBar progressBar;
    File selFile;
    String welcome="此界面是发送文件界面！";
    SenderPage(){
        setLayout(new GridLayout(3,1));
        init();
        initTitle();
        initFileBody();
    }
    void init(){
        hostInput=new JTextField();
        portInput=new JTextField();
        connectBt=new JButton();
        pubKeyView=new JTextField();
        keyInput=new JTextField();
        title=new JPanel();
        msgBody=new JPanel();
        pubKeyBody=new JPanel();
        fileBody=new JPanel();
        fileBtBody=new JPanel();

        outMsg=new JTextArea();

        sendBt=new JButton("发送");
        enFileBt=new JButton("加密");
        deFileBt=new JButton("解密");
        selFileBt=new JButton("选择文件");
        openFileBt=new JButton("打开");
        textMsg = new JTextField(welcome);
    }
    /*
     * title部分
     */
    void initTitle(){

        JPanel titleBody=new JPanel();
        title.setLayout(new GridLayout(3,1));

        textMsg.setForeground(Color.RED);;
        textMsg.setHorizontalAlignment(JTextField.CENTER);
        textMsg.setFont(new Font ("宋体",Font.BOLD,20));
        textMsg.setEditable(false);
        JTextField ip=new JTextField("请输入ip:");
        ip.setEditable(false);
        ip.setBorder(null);
        hostInput.setText("127.0.0.1");
        hostInput.setPreferredSize(new Dimension (80,20));
        hostInput.setHorizontalAlignment(JTextField.CENTER);

        JTextField p = new JTextField("端口：");
        p.setBackground(null);
        p.setBorder(null);
        portInput.setText("8080");
        portInput.setHorizontalAlignment(JTextField.CENTER);
        portInput.setPreferredSize(new Dimension (40,20));
        connectBt.setText("下载公钥");
        connectBt.setFocusPainted(false);
        JTextField pubk = new JTextField("请输入您获得的公钥：");
        pubk.setEditable(false);
        pubk.setBorder(null);
        pubKeyView.setPreferredSize(new Dimension (200,20));
        pubKeyBody.add(pubk);
        pubKeyBody.add(pubKeyView);

        titleBody.add(ip);
        titleBody.add(hostInput);
        titleBody.add(p);
        titleBody.add(portInput);
        titleBody.add(connectBt);
        title.add(textMsg);
        title.add(titleBody);
        title.add(pubKeyBody);
        add(title);
        /*
        *中间部分
        */

        JScrollPane outMsgScroll=new JScrollPane(outMsg);
        outMsgScroll.setPreferredSize(new Dimension (420,150));
        outMsg.setEditable(false);
        add(outMsgScroll);

        connectBt.addActionListener(this);
//        scrollPane.setBounds(13, 10, 420, 150);

    }

    /*
     *文件部分
     */
    private void initFileBody() {
        fileBody.setLayout(new GridLayout(3,1));
        keyInput.setPreferredSize(new Dimension (300,20));
        selFileBt.setPreferredSize(new Dimension (280,40));

        JTextField key = new JTextField("请输入加密文件用的密钥：");
        key.setEditable(false);
        key.setBorder(null);
        key.setForeground(Color.RED);
        key.setFont(new Font ("宋体",Font.BOLD,15));
        fileBtBody.add(selFileBt);
        fileBtBody.add(enFileBt);
        fileBtBody.add(deFileBt);
        fileBtBody.add(sendBt);
        fileBtBody.add(openFileBt);
        fileBody.add(key);
        fileBody.add(keyInput);
        fileBody.add(fileBtBody);
        add(fileBody);
        selFileBt.addActionListener(this);
        enFileBt.addActionListener(this);
        deFileBt.addActionListener(this);
        sendBt.addActionListener(this);
        openFileBt.addActionListener(this);
    }

    public void print(String str){
        System.out.println("输出："+str);
        outMsg.append(">> "+str+"\n");
        outMsg.setSelectionStart(outMsg.getText().length());
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals(selFileBt.getActionCommand())) selectFile();
        else if (e.getActionCommand().equals(connectBt.getActionCommand())) downloadPubKey();
        else if (e.getActionCommand().equals(enFileBt.getActionCommand())) encodeSelFile();
        else if (e.getActionCommand().equals(deFileBt.getActionCommand())) decodeSelFile();
        else if (e.getActionCommand().equals(sendBt.getActionCommand())) sendFile();
        else if (e.getActionCommand().equals(openFileBt.getActionCommand())) openFile();

    }

    private void openFile() {
        if(selFile==null||!selFile.isFile()){
            print("请选择文件！");
            return;
        }
        try {
            Runtime.getRuntime().exec("explorer.exe /select," + selFile.getPath());
        } catch (IOException e) {
            e.printStackTrace();
            print("打开失败！");
        }
    }

    private void sendFile() {
        String key = keyInput.getText();
        if(selFile==null||!selFile.isFile()){
            print("请选择文件！");
            return;
        }
        if (key.length()==0){
            print("您没有输入秘钥哦！");
            return;
        }
        if ("bbyend".equals(BBYFileTool.getSuffix(selFile.getName()))){
            print("该文件不是密文，发送会很危险！");
            return;
        }
        if (downloadPubKey()){
            String pubKey=pubKeyView.getText();
            try {
                print("准备发送文件:"+selFile.getName());
                print("正在用公钥加密对称秘钥...");
                print("公钥："+pubKey);
                print("对称秘钥："+key);
                String enkey=RSA.encrypt(key, RSA.getPublicKey(pubKey));
                print("用公钥加密后的对称秘钥："+enkey);
                String md5= MD5.getMD5(selFile);
                print("文件的MD5:"+md5);
                Cilent cilent = new Cilent(hostInput.getText(),Integer.parseInt(portInput.getText()),this);
                cilent.sendFile(selFile,md5,enkey);
            } catch (Exception e) {
                e.printStackTrace();
                print("公钥有误！");
                return;
            }


        }
    }

    private void decodeSelFile() {
        String key = keyInput.getText();
        if(selFile==null||!selFile.isFile()){
            print("请选择文件！");
            return;
        }
        if (key.length()==0){
            print("您没有输入秘钥哦！");
            return;
        }
        if ("bbyend".equals(BBYFileTool.getSuffix(selFile.getName()))){
            print("该文件不是密文，无法解密！");
            return;
        }
        try {
            File outfile=new File(Config.DECODE_DIR+selFile.getName().replace(".bbyend",""));
            if (!outfile.exists()) outfile.createNewFile();
            print("正在解密文件 "+selFile.getName()+",文件大小："+(selFile.length()/1024)+" Byte");
            print("对称秘钥："+key);
            BufferedReader br=new BufferedReader(new FileReader(selFile));
            OutputStream os = new FileOutputStream(outfile);
            String line;
            long bytes=0;
            while ((line=br.readLine())!=null){
                byte bts[]=AES.aesDecrypt(line,key);//调用实验一的代码进行解密
                if (bts==null){
                    print("文件格式错误，解密失败！");
                    return;
                }
                os.write(bts);
                os.flush();
            }
            br.close();
            os.close();
            print("解密完成！");
            print("明文文件："+outfile.getPath());
            selFile=outfile;
            selFileBt.setText(selFile.getName());
        } catch (Exception e) {
            e.printStackTrace();
            print("文件解密失败！");
            return;
        }
    }

    private void encodeSelFile() {
        if(selFile==null||!selFile.isFile()){
            print("请选择文件！");
            return;
        }
        String key = keyInput.getText();
        if (key.length()==0){
            print("您没有输入秘钥哦！");
            return;
        }
        try {
            File outfile=new File(Config.ENCODE_DIR+selFile.getName()+".bbyend");
            if (!outfile.exists()) outfile.createNewFile();
            print("正在加密文件 "+selFile.getName()+",文件大小："+(selFile.length()/1024)+" Byte");
            InputStream is=new FileInputStream(selFile);
            BufferedWriter bw=new BufferedWriter(new FileWriter(outfile));
            byte buf[]=new byte[1024];
            long bytes=0;
            print("加密中：");
            while ((bytes=is.read(buf))>0){//分组加密每次读取1024字节
                if (bytes==1024){
                    bw.write(AES.aesEncrypt(buf,key));//调用实验一的代码进行加密
                    bw.write('\n');
                } else {
                    ByteBuffer bb=ByteBuffer.allocate((int) bytes);
                    for (byte b:buf){
                        if ((--bytes)<0) break;
                        bb.put(b);
                    }
                    bw.write(AES.aesEncrypt(bb.array(),key));
                }
                bw.flush();
            }
            is.close();
            bw.close();
            print("加密完成！");
            print("对称秘钥："+key);
            print("密文文件："+outfile.getPath());
            selFile=outfile;
            selFileBt.setText(selFile.getName());
        } catch (Exception e) {
            e.printStackTrace();
            print("文件加密失败！");
        }
    }

    private boolean downloadPubKey() {
        String host = hostInput.getText();
        print("测试连接并从"+host+"下载公钥！");
        if(host.length()==0){
            print("ip地址为空！！");
            return false;
        }
        int port;
        try {
            port = Integer.parseInt(portInput.getText());
            Cilent cilent = new Cilent(host,port);
            String pubKey=cilent.downloadPubKey();
            pubKeyView.setText(pubKey);
            print("得到公钥："+pubKey);
            return true;
        }catch (IOException ioException){
            print("连接失败，请检查ip和端口设置，以及接收端配置！");
        } catch (Exception exception) {
            print("端口号必须是数字！！");
        }
        return false;
    }
    private void selectFile(){
        try {
            print("开始选择文件！");
            JFileChooser chooser=new JFileChooser();
            chooser.setCurrentDirectory(selFile==null? new File("./"):selFile.getParentFile());
            chooser.setFileSelectionMode(JFileChooser.FILES_ONLY );
            chooser.showDialog(new JLabel(), "选择");
            File file=chooser.getSelectedFile();
            if(!file.isFile()){
                print("请选择文件,而不是文件夹！");
                return;
            }
            if (file.length()>1024*1024*10){
                print("文件太大！需要小于10MB！");
                return;
            }
            selFile=file;
            selFileBt.setText(file.getName());
            print("选择文件："+selFile.getPath());
        }catch (Exception exception){
            print("未选择！");
            return;
        }
    }
}
